package com.bw.gmall.app.ods;

import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

public class DmpFamilyDataGenerator {

    // 行为类型及权重
    private static final Map<String, Double> BEHAVIOR_CONFIG = new HashMap<>();
    // 商品类目配置
    private static final List<Map<String, Object>> PRODUCT_CATEGORY_CONFIG = new ArrayList<>();
    // 年龄段配置
    private static final List<String> AGE_SEGMENTS = new ArrayList<>();

    static {
        // 初始化行为配置
        BEHAVIOR_CONFIG.put("购买", 1.0);
        BEHAVIOR_CONFIG.put("搜索", 0.8);
        BEHAVIOR_CONFIG.put("收藏", 0.4);
        BEHAVIOR_CONFIG.put("浏览", 0.2);

        // 初始化商品类目配置
        // 女宝指向类目
        Map<String, Object> girlCategory1 = new HashMap<>();
        girlCategory1.put("category", "童装/婴儿装/亲子装>女童连衣裙");
        girlCategory1.put("gender", "女");
        girlCategory1.put("categoryWeight", 1.0);
        girlCategory1.put("ageSegment", "3-6岁");
        girlCategory1.put("titleTemplate", "女童连衣裙夏季公主裙{age}宝宝裙子");
        girlCategory1.put("keywordsTemplate", "女童,{age},连衣裙");
        PRODUCT_CATEGORY_CONFIG.add(girlCategory1);

        Map<String, Object> girlCategory2 = new HashMap<>();
        girlCategory2.put("category", "玩具/童车/益智/积木/模型>毛绒布艺类玩具");
        girlCategory2.put("gender", "女");
        girlCategory2.put("categoryWeight", 1.0);
        girlCategory2.put("ageSegment", "24-36个月");
        girlCategory2.put("titleTemplate", "女宝宝洋娃娃公主玩具{age}安抚玩偶");
        girlCategory2.put("keywordsTemplate", "女宝,{age},毛绒玩具");
        PRODUCT_CATEGORY_CONFIG.add(girlCategory2);

        // 男宝指向类目
        Map<String, Object> boyCategory1 = new HashMap<>();
        boyCategory1.put("category", "童装/婴儿装/亲子装>男童T恤");
        boyCategory1.put("gender", "男");
        boyCategory1.put("categoryWeight", 1.0);
        boyCategory1.put("ageSegment", "3-6岁");
        boyCategory1.put("titleTemplate", "男童短袖T恤夏季{age}纯棉上衣");
        boyCategory1.put("keywordsTemplate", "男童,{age},T恤");
        PRODUCT_CATEGORY_CONFIG.add(boyCategory1);

        Map<String, Object> boyCategory2 = new HashMap<>();
        boyCategory2.put("category", "玩具/童车/益智/积木/模型>电动遥控玩具");
        boyCategory2.put("gender", "男");
        boyCategory2.put("categoryWeight", 1.0);
        boyCategory2.put("ageSegment", "6-12岁");
        boyCategory2.put("titleTemplate", "男童电动遥控飞机{age}玩具");
        boyCategory2.put("keywordsTemplate", "男童,{age},遥控飞机");
        PRODUCT_CATEGORY_CONFIG.add(boyCategory2);

        // 中性类目
        Map<String, Object> neutralCategory1 = new HashMap<>();
        neutralCategory1.put("category", "童装/婴儿装/亲子装>连身衣/爬服/哈衣");
        neutralCategory1.put("gender", "中性");
        neutralCategory1.put("categoryWeight", 0.5);
        neutralCategory1.put("ageSegment", "0-3个月");
        neutralCategory1.put("titleTemplate", "婴儿连身衣春秋款{age}男女通用");
        neutralCategory1.put("keywordsTemplate", "婴儿,{age},通用");
        PRODUCT_CATEGORY_CONFIG.add(neutralCategory1);

        Map<String, Object> neutralCategory2 = new HashMap<>();
        neutralCategory2.put("category", "玩具/童车/益智/积木/模型>STEAM教具");
        neutralCategory2.put("gender", "中性");
        neutralCategory2.put("categoryWeight", 0.5);
        neutralCategory2.put("ageSegment", "6-12岁");
        neutralCategory2.put("titleTemplate", "儿童STEAM积木套装{age}益智玩具");
        neutralCategory2.put("keywordsTemplate", "STEAM,{age},积木");
        PRODUCT_CATEGORY_CONFIG.add(neutralCategory2);

        // 孕产妇类目
        Map<String, Object> maternityCategory1 = new HashMap<>();
        maternityCategory1.put("category", "孕产妇用品>防辐射服");
        maternityCategory1.put("gender", "无");
        maternityCategory1.put("categoryWeight", 1.0);
        maternityCategory1.put("ageSegment", "孕早期(0-12周)");
        maternityCategory1.put("titleTemplate", "孕妇防辐射服{age}马甲");
        maternityCategory1.put("keywordsTemplate", "孕妇,{age},防辐射马甲");
        PRODUCT_CATEGORY_CONFIG.add(maternityCategory1);

        Map<String, Object> maternityCategory2 = new HashMap<>();
        maternityCategory2.put("category", "孕产妇用品>待产包");
        maternityCategory2.put("gender", "无");
        maternityCategory2.put("categoryWeight", 1.0);
        maternityCategory2.put("ageSegment", "孕晚期(29-40周)");
        maternityCategory2.put("titleTemplate", "孕妇待产包{age}全套");
        maternityCategory2.put("keywordsTemplate", "孕妇,{age},待产包");
        PRODUCT_CATEGORY_CONFIG.add(maternityCategory2);

        // 初始化年龄段配置
        AGE_SEGMENTS.add("孕早期(0-12周)");
        AGE_SEGMENTS.add("孕中期(13-28周)");
        AGE_SEGMENTS.add("孕晚期(29-40周)");
        AGE_SEGMENTS.add("0-3个月");
        AGE_SEGMENTS.add("3-6个月");
        AGE_SEGMENTS.add("6-12个月");
        AGE_SEGMENTS.add("12-24个月");
        AGE_SEGMENTS.add("24-36个月");
        AGE_SEGMENTS.add("3-6岁");
        AGE_SEGMENTS.add("6-12岁");
    }

    // 计算时间衰减系数
    private static double getTimeDecayCoeff(LocalDateTime behaviorDate, LocalDateTime currentDate) {
        long daysDiff = java.time.temporal.ChronoUnit.DAYS.between(behaviorDate, currentDate);
        if (daysDiff <= 30) {
            return 1.0;
        } else if (daysDiff <= 60) {
            return 0.5;
        } else {
            return 0.2;
        }
    }

    // 计算性别得分
    private static double[] calculateGenderScore(String gender, double categoryWeight, double behaviorWeight, double timeDecayCoeff) {
        double boyScore = 0.0;
        double girlScore = 0.0;
        if ("男".equals(gender)) {
            boyScore = categoryWeight * behaviorWeight * timeDecayCoeff;
        } else if ("女".equals(gender)) {
            girlScore = categoryWeight * behaviorWeight * timeDecayCoeff;
        } else {
            double score = categoryWeight * behaviorWeight * timeDecayCoeff / 2;
            boyScore = score;
            girlScore = score;
        }
        return new double[]{boyScore, girlScore};
    }

    // 计算年龄段得分
    private static double calculateAgeScore(double behaviorWeight) {
        return behaviorWeight * 1.0;
    }

    // 生成用户ID
    private static String generateUserId(int index) {
        return "U" + (12345678 + index);
    }

    // 生成行为时间
    private static LocalDateTime generateBehaviorTime(LocalDateTime currentDate, Random random) {
        int daysAgo = random.nextInt(61); // 0-60天内
        return currentDate.minusDays(daysAgo)
                .withHour(random.nextInt(24))
                .withMinute(random.nextInt(60))
                .withSecond(random.nextInt(60));
    }

    // 判定宝宝性别
    private static String determineBabyGender(double boyTotal, double girlTotal) {
        if (boyTotal > girlTotal) {
            return "男";
        } else if (girlTotal > boyTotal) {
            return "女";
        } else {
            return "未识别";
        }
    }

    // 判定宝宝年龄
    private static String determineBabyAge(Map<String, Double> ageScores) {
        String maxAge = null;
        double maxScore = -1;
        for (Map.Entry<String, Double> entry : ageScores.entrySet()) {
            if (entry.getValue() > maxScore) {
                maxScore = entry.getValue();
                maxAge = entry.getKey();
            }
        }

        boolean isDominant = true;
        for (Map.Entry<String, Double> entry : ageScores.entrySet()) {
            if (!entry.getKey().equals(maxAge) && maxScore < 2 * entry.getValue()) {
                isDominant = false;
                break;
            }
        }

        if (isDominant) {
            return maxAge;
        } else {
            List<String> similarAges = new ArrayList<>();
            for (Map.Entry<String, Double> entry : ageScores.entrySet()) {
                if (maxScore - entry.getValue() <= 0.2 * maxScore) {
                    similarAges.add(entry.getKey());
                }
            }
            return similarAges.get(new Random().nextInt(similarAges.size()));
        }
    }

    public static void generateDmpFamilyData(int numRecords, String csvFilePath) {
        LocalDateTime currentDate = LocalDateTime.of(2025, 5, 1, 0, 0, 0);
        Random random = new Random();
        List<Map<String, Object>> data = new ArrayList<>();

        for (int i = 0; i < numRecords; i++) {
            String userId = generateUserId(i);
            LocalDateTime behaviorTime = generateBehaviorTime(currentDate, random);

            Map<String, Object> categoryCfg = PRODUCT_CATEGORY_CONFIG.get(random.nextInt(PRODUCT_CATEGORY_CONFIG.size()));
            String behaviorType = new ArrayList<>(BEHAVIOR_CONFIG.keySet()).get(random.nextInt(BEHAVIOR_CONFIG.size()));

            String category = (String) categoryCfg.get("category");
            String gender = (String) categoryCfg.get("gender");
            double categoryWeight = (double) categoryCfg.get("categoryWeight");
            String ageSegment = (String) categoryCfg.get("ageSegment");
            double behaviorWeight = BEHAVIOR_CONFIG.get(behaviorType);
            double timeDecayCoeff = getTimeDecayCoeff(behaviorTime, currentDate);

            String titleTemplate = (String) categoryCfg.get("titleTemplate");
            String productTitle = titleTemplate.replace("{age}", ageSegment);
            String keywordsTemplate = (String) categoryCfg.get("keywordsTemplate");
            String productKeyword = keywordsTemplate.replace("{age}", ageSegment);

            double[] genderScores = calculateGenderScore(gender, categoryWeight, behaviorWeight, timeDecayCoeff);
            double boyScore = genderScores[0];
            double girlScore = genderScores[1];
            double ageScore = calculateAgeScore(behaviorWeight);

            Map<String, Object> record = new HashMap<>();
            record.put("user_id", userId);
            record.put("behavior_type", behaviorType);
            record.put("behavior_time", behaviorTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            record.put("product_category", category);
            record.put("product_title", productTitle);
            record.put("product_keyword", productKeyword);
            record.put("category_weight", categoryWeight);
            record.put("behavior_weight", behaviorWeight);
            record.put("time_decay_coeff", timeDecayCoeff);
            record.put("boy_score", Math.round(boyScore * 100.0) / 100.0);
            record.put("girl_score", Math.round(girlScore * 100.0) / 100.0);
            record.put("age_segment", ageSegment);
            record.put("age_score", Math.round(ageScore * 100.0) / 100.0);

            data.add(record);
        }

        // 聚合用户性别得分
        Map<String, Double> userBoyScores = new HashMap<>();
        Map<String, Double> userGirlScores = new HashMap<>();
        for (Map<String, Object> record : data) {
            String userId = (String) record.get("user_id");
            double boyScore = (double) record.get("boy_score");
            double girlScore = (double) record.get("girl_score");
            userBoyScores.put(userId, userBoyScores.getOrDefault(userId, 0.0) + boyScore);
            userGirlScores.put(userId, userGirlScores.getOrDefault(userId, 0.0) + girlScore);
        }

        // 聚合用户年龄段得分
        Map<String, Map<String, Double>> userAgeScoresMap = new HashMap<>();
        for (Map<String, Object> record : data) {
            String userId = (String) record.get("user_id");
            String ageSegment = (String) record.get("age_segment");
            double ageScore = (double) record.get("age_score");
            userAgeScoresMap.computeIfAbsent(userId, k -> new HashMap<>())
                    .put(ageSegment, userAgeScoresMap.get(userId).getOrDefault(ageSegment, 0.0) + ageScore);
        }

        // 写入CSV文件
        try (FileWriter writer = new FileWriter(csvFilePath)) {
            // 写入表头
            writer.write("user_id,behavior_type,behavior_time,product_category,product_title,product_keyword,category_weight,behavior_weight,time_decay_coeff,boy_score,girl_score,baby_gender,age_segment,age_score,baby_age\n");

            for (Map<String, Object> record : data) {
                String userId = (String) record.get("user_id");
                double boyTotal = userBoyScores.getOrDefault(userId, 0.0);
                double girlTotal = userGirlScores.getOrDefault(userId, 0.0);
                String babyGender = determineBabyGender(boyTotal, girlTotal);

                Map<String, Double> ageScores = userAgeScoresMap.getOrDefault(userId, new HashMap<>());
                String babyAge = determineBabyAge(ageScores);

                writer.write(String.format("%s,%s,%s,%s,%s,%s,%.1f,%.1f,%.1f,%.2f,%.2f,%s,%s,%.2f,%s\n",
                        record.get("user_id"),
                        record.get("behavior_type"),
                        record.get("behavior_time"),
                        record.get("product_category"),
                        record.get("product_title"),
                        record.get("product_keyword"),
                        record.get("category_weight"),
                        record.get("behavior_weight"),
                        record.get("time_decay_coeff"),
                        record.get("boy_score"),
                        record.get("girl_score"),
                        babyGender,
                        record.get("age_segment"),
                        record.get("age_score"),
                        babyAge));
            }

            System.out.println("数据生成完成！共" + numRecords + "条记录，已保存为：" + csvFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        int numRecords = 10000; // 生成1万条数据，可修改
        String csvFilePath = "达摩盘家庭特征数据.csv";
        generateDmpFamilyData(numRecords, csvFilePath);
    }
}